package com.runa.rccprotocol.analysis.huizhong;

import com.alibaba.fastjson.JSON;
import com.runa.monitor.comm.dto.newComm.CurrentData;
import com.runa.monitor.comm.dto.newComm.HotMeterVO;
import com.runa.monitor.comm.dto.newComm.ValveVO;
import com.runa.persistence.task.RequestPendingTask;
import com.runa.persistence.task.TaskTypeEnum;
import com.runa.persistence.util.LogUtil;
import com.runa.protocol.analysis.ShellBufferAnalysis;
import com.runa.protocol.dto.DtuReport;
import com.runa.protocol.dto.IInterData;
import com.runa.protocol.enums.ByteOrder;
import com.runa.protocol.util.ByteUtil;
import com.runa.protocol.util.UtilTime;
import com.runa.rccprotocol.dto.HuiZhongOne.HuiZhongOneReportAck;
import com.runa.rccprotocol.dto.equdata.EquData;
import com.runa.rccprotocol.dto.runa.RunaConcenAffirmDeny;
import com.runa.rccprotocol.dto.runa.RunaConcenResponseData;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
public class HuiZhongOneAnalysis extends ShellBufferAnalysis<byte[]> {

    public HuiZhongOneAnalysis() {
        super(null, 0);
    }

    @Override
    public int fill(byte[] data, int size,String n) {
        String message = ByteUtil.byteToHexString(data, 0, size);
        log.debug("汇中: {} {}", n, message);

        if (size < 6) return -1;
        int begin;
        for (begin = 0; begin < size; begin++) {
            if ((data[begin] & 0xff) == 0x68
                    && data[begin + 5] == 0x68) {
                break;
            }
        }
        int L = (((data[begin + 1] & 0xff)) + (data[begin + 2] << 8)) >> 2;
        if (size < L + 8) {
            return -1;
        }
        if ((data[begin + 6 + L] != ByteUtil.sum(data, begin + 6, L))) {
            return -1;
        }
        int type = data[begin + 6] & 0xff;
        switch (type) {
            //注册包或者心跳包
            case 0xC9:
                no(data);
                LogUtil.linkDetect(netEquNo, "汇中", data, size, "链路测试");
                DtuReport dtuReport = new DtuReport(netEquNo);
                dtuReport.setMustAck(true);
                dtuReport.setAck(new HuiZhongOneReportAck(netEquNo));
                this.interData = dtuReport;
                break;
            case 0x88:
                if ((data[begin + 12] & 0xff) == 0x0C && (data[begin + 14] & 0xff) == 0x05) {//一类数据Fn为5
                    no(data);
                    RunaConcenResponseData responseData = new RunaConcenResponseData();
                    responseData.addRepData(handleData(data, begin, RequestPendingTask.isReadMeter(netEquNo)));
                    interData = responseData;
                }
            default:
                if ((data[begin + 12] & 0xff) == 0x00) {
                    if ((data[begin + 14] & 0xff) == 0x01) {
                        // 确认
                        interData = new RunaConcenAffirmDeny(netEquNo, true);
                    } else if ((data[begin + 14] & 0xff) == 0x02) {
                        // 否认
                        interData = new RunaConcenAffirmDeny(netEquNo, false);
                    }
                }
        }
        return 0;
    }

    public CurrentData handleData(byte[] data, int index, boolean isMeter) {
        try {
            index += 18;
            Date readTime = new SimpleDateFormat("yyMMddHHmmss").parse(ByteUtil.byteToHexStringFlip(data, index, 6));
            index += 6;

            int indexNo = (ByteUtil.byteToUShort(data, index, ByteOrder.BA));
            index += 3;

            String serial = (ByteUtil.byteToHexStringFlip(data, index, 7).replaceAll("F", ""));
            index += 7;

            int valid = data[index++];

            if (valid == 0x26) {
                HotMeterVO hotMeterVO = handleMeterData(data, index, indexNo, serial, readTime);
                if (isMeter) {
                    return hotMeterVO;
                }
                return handleValveData(data, index+37, indexNo, readTime, hotMeterVO.getMeterDate());
            } else {
                if (isMeter) {
                    HotMeterVO meterVO = new HotMeterVO();
                    meterVO.setMeterSerial(serial);
                    meterVO.setSuccess(false);
                    return meterVO;
                } else {
                    ValveVO valveVO = new ValveVO();
                    valveVO.setIndex(indexNo+100);
                    valveVO.setSuccess(false);
                    return valveVO;
                }
            }
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }



    private HotMeterVO handleMeterData(byte[] data, int index, int indexNo, String serial, Date readTime) {
        HotMeterVO meterVO = new HotMeterVO();
        meterVO.setIndexNo(indexNo);
        meterVO.setMeterSerial(serial);
        meterVO.setReadDate(readTime);
        //累积热量
        double theCurrentHeatSum = ByteUtil.bcdToInt(data, index, 4, false) * 0.01;
        meterVO.setAccHeat((float) theCurrentHeatSum);
        index += 4;
        ++index;
        //瞬时流量
        double instantaneousDelivery = ByteUtil.bcdToInt(data, index, 4, false) * 0.0001;
        meterVO.setFlow((float) instantaneousDelivery);
        index += 4;
        ++index;
        //累计流量
        double cumulativeDischarge = ByteUtil.bcdToInt(data, index, 4, false) * 0.01;
        meterVO.setAccFlow((float) cumulativeDischarge);
        index += 5;
        //进水温
        double intoTheWater = ByteUtil.bcdToInt(data, index, 3, false) * 0.01;
        meterVO.setSupplyTemp((float) intoTheWater);
        index += 3;
        //回水温度
        double returnWaterTemperature = ByteUtil.bcdToInt(data, index, 3, false) * 0.01;
        meterVO.setReturnTemp((float) returnWaterTemperature);
        index += 3;
        //热功率
//        ++index;
        double thermalPower = ByteUtil.bcdToInt(data, index, 4, false) * 0.01;
        meterVO.setPower((float) thermalPower);
        index += 4;
        ++index;
        //无单位,累计工作时间
        int openTime = ByteUtil.bcdToInt(data, index, 4, false);
        meterVO.setWorkTime(openTime);
        index += 4;

        // 状态
        byte status = data[index++];
        if (status != 0) {
            meterVO.setFaultCode(meterFaultCodeList(status));
        }
        meterVO.setStatus(ByteUtil.byteToHexString(status));
        meterVO.setMeterDate(UtilTime.StringToDate(ByteUtil.bcd2str(data, index, 6, false), "yyMMddHHmmss"));
        index += 6;

        return meterVO;
    }

    private List<String> meterFaultCodeList(byte status) {
        List<String> faultCodeList = new ArrayList<>();
        byte l = (byte)(status & 0x0F);
        switch (l) {
            case 5:
                faultCodeList.add("传感器和换能器之间通讯故障，无通讯");
                break;
            case 6:
                faultCodeList.add("E2PROM 损坏");
        }
        if ((status & 1) == 1) {
            faultCodeList.add("电池电压低于3.37V，需要更换电池");
        }
        if ((status >> 1 & 1) == 1) {
            faultCodeList.add("空管或者换能器故障无测量信号");
        }
        if ((status >> 2 & 1) == 1) {
            faultCodeList.add("电池电压低于3.3V，必须更换电池");
        }
        if ((status >> 4 & 1) == 1) {
            faultCodeList.add("供水温度传感器故障（短路、开路）或供水温度低于2");
        }
        if ((status >> 5 & 1) == 1) {
            faultCodeList.add("供水温度超出150");
        }
        if ((status >> 6 & 1) == 1) {
            faultCodeList.add("回水温度传感器故障（短路、开路）或回水温度低于2");
        }
        if ((status >> 7 & 1) == 1) {
            faultCodeList.add("回水温度超出150");
        }

        return faultCodeList;
    }

    private ValveVO handleValveData(byte[] data, int index, int indexNo, Date readTime, Date equDate) {
        ValveVO valveVO = new ValveVO();
        valveVO.setIndex(indexNo+100);
        valveVO.setReadTime(readTime);
        valveVO.setValveDate(equDate);
        byte status = data[index++];
        valveVO.setStatus(ByteUtil.byteToHexString(status));
        int openStatus = status & 0x03;
        if (openStatus == 0) {
            // 开
            valveVO.setActOpen(100f);
        } else if (openStatus == 1) {
            // 关
            valveVO.setActOpen(0f);
        } else if (openStatus == 2) {
            // 无
            List<String> faultCodeList = new ArrayList<>();
            faultCodeList.add("无");
            valveVO.setFaultCode(faultCodeList);
        } else {
            // 异常
            valveVO.setFaultCode(valveFaultCodeList(status));
        }

        if ((status >> 7 & 1) == 1) {
            // 调节阀
            valveVO.setActOpen((float)data[index++]);
        }
        return valveVO;
    }


    private List<String> valveFaultCodeList(byte status) {
        List<String> faultCodeList = new ArrayList<>();
        if ((status >> 2 & 1) == 1) {
            faultCodeList.add("室温控制器电池电压欠压");
        }
        return faultCodeList;
    }


    private void no(byte[] data) {
        netEquNo = ByteUtil.bcd2str(data, 7, 5, false);
    }


    public static void main(String[] args) {
        RequestPendingTask.addTask("1742000048", new RequestPendingTask(TaskTypeEnum.READ_METER));
        HuiZhongOneAnalysis analysis = new HuiZhongOneAnalysis();
        String heart = "683200320068C99113972802027000000100A116".replace(" ", "");
//        String heart = "68 32 00 32 00 68 C9 01 10 11 27 00 02 7E 00 00 04 00 96 16".replace(" ", "");
        String heatMeter = "681B011B01688848000042170C600501010126392306012562000C11146920F1FFFF2610126705050000000035657375002C5520005924000000000017434402000037270407012502000000E016 ";
        byte[] bytes = ByteUtil.hexStringToByte(heatMeter);
//        byte[] bytes = s.getBytes();
        analysis.fill(bytes, bytes.length,"");
        IInterData gain = analysis.gain();
        System.out.println(JSON.toJSONString(gain));

//        int i = DigitalUtil.calcCrc16(ByteUtil.hexStringToByte("7E 0D 68 34 20 11 10 0F 1E 07 12 A5 5A D8 8D 7E".replace(" ","")), 1, 12);
//        int i = DigitalUtil.CRC16_XMODEM(ByteUtil.hexStringToByte("0D 68 34 20 11 10 0F 1E 07 12 A5 5A"));
//        System.out.println(i);
    }
}
